package com.molichuxing.gateway.bff.financial.services.impl;

import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.framework.utils.DingTalkUtil;
import com.molichuxing.framework.utils.EmailUtil;
import com.molichuxing.framework.utils.ObjectCastUtil;
import com.molichuxing.gateway.bff.financial.convertor.Convert;
import com.molichuxing.gateway.bff.financial.entity.response.ReceiptDownloadVo;
import com.molichuxing.gateway.bff.financial.services.FinancialDownloadBffService;
import com.molichuxing.gateway.utils.PoiExcelUtil;
import com.molichuxing.gateway.utils.entity.UserEntity;
import com.molichuxing.services.business.dto.response.PaymentDownloadBizDto;
import com.molichuxing.services.business.service.PaymentBizService;
import com.molichuxing.services.infrastructure.dto.response.CarDto;
import com.molichuxing.services.infrastructure.dto.response.OrderScheduleDto;
import com.molichuxing.services.infrastructure.dto.response.OrderSubcompanyDto;
import com.molichuxing.services.infrastructure.dto.response.UserDto;
import com.molichuxing.services.infrastructure.service.CarService;
import com.molichuxing.services.infrastructure.service.OrderScheduleService;
import com.molichuxing.services.infrastructure.service.OrderService;
import com.molichuxing.services.infrastructure.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;

/**
 * 财务导出bff
 *
 * @author zoumingyu
 * @date 2019年12月16日
 *
 */
@Service("financialDownloadBffService")
public class FinancialDownloadBffServiceImpl implements FinancialDownloadBffService {
	private static final Logger logger = LoggerFactory.getLogger(FinancialDownloadBffServiceImpl.class);

	@Value("${profiles.active.explain}")
	private String EXPLAIN;

	@Value("${email_account}")
	private String EMAIL_ACCOUNT;

	@Value("${email_password}")
	private String EMAIL_PASSWORD;

	@Resource
	private PaymentBizService paymentBizService;

	@Resource
	private OrderService orderService;

	@Resource
	private OrderScheduleService orderScheduleService;

	@Resource
	private UserService userService;

	@Resource
	private CarService carService;

	/**
	 * 查询收款台账导出数据
	 *
	 * @param selectParams
	 * @return
	 * @throws Exception
	 */
	@Override
	public List<ReceiptDownloadVo> getReceiptStandingBookDownload(Map<String, Object> selectParams) throws Exception {
		List<ReceiptDownloadVo> result = null;
		// 判断是否选择查询
		String paymentIds = ObjectCastUtil.castString(selectParams.get("paymentIds"));
		if (StringUtils.isNotBlank(paymentIds)) {
			// 选择导出
			selectParams.remove("businessType");
			selectParams.remove("orderCode");
			selectParams.remove("thirdPayNumber");
			selectParams.remove("userName");
			selectParams.remove("startPayTime");
			selectParams.remove("endPayTime");
			selectParams.remove("payWay");
			selectParams.remove("payType");
			selectParams.put("paymentIds", Arrays.asList(paymentIds.split(",")));
		} else {
			// 转换用户信息
			if (!xlateUser(selectParams)) {
				return result;
			}
		}
		// 查询支付信息
		List<PaymentDownloadBizDto> paymentBizs = paymentBizService.getReceiptStandingBookDownload(selectParams);
		if (paymentBizs == null || paymentBizs.isEmpty()) {
			return result;
		}
		result = new ArrayList<>();

		// 用户id集合
		Set<Integer> userIds = new HashSet<>();
		// 排期ids
		List<Integer> scheduleIds = new ArrayList<>();
		// 订单号list
		Set<Long> orderCodes = new HashSet<>();
		for (PaymentDownloadBizDto paymentBizDto : paymentBizs) {
			userIds.add(paymentBizDto.getUserId());
			orderCodes.add(paymentBizDto.getOrderCode());
			if (paymentBizDto.getScheduleId() > 0) {
				scheduleIds.add(paymentBizDto.getScheduleId());
			}
		}
		// 查询用户
		Map<Integer, UserDto> userMap = userService.getUsers(new ArrayList<>(userIds));
		// 查询订单
		Map<Long, OrderSubcompanyDto> orderMap = orderService.getOrderAndSubcompany(new ArrayList<>(orderCodes));
		// 车辆信息
		Map<Integer, CarDto> carMap = null;
		if (orderMap != null && !orderMap.isEmpty()) {
			// 车辆ids
			Set<Integer> carIds = new HashSet<>();
			for (OrderSubcompanyDto dto : orderMap.values()) {
				carIds.add(dto.getCarId());
			}
			carMap = carService.getCarByIds(new ArrayList<>(carIds));
		}
		// 查询排期
		Map<Integer, OrderScheduleDto> scheduleMap = null;
		if (!scheduleIds.isEmpty()) {
			scheduleMap = orderScheduleService.getOrderSchedule(scheduleIds);
		}

		for (PaymentDownloadBizDto paymentBizDto : paymentBizs) {
			ReceiptDownloadVo receiptDownloadVo = Convert.toReceiptDownloadVo(paymentBizDto);
			// 用户
			UserDto userDto = userMap == null ? null
					: userMap.isEmpty() ? null : userMap.get(paymentBizDto.getUserId());
			// 用户姓名
			receiptDownloadVo.setRealName(userDto == null ? null : userDto.getRealName());

			// 排期
			if (scheduleMap != null && !scheduleMap.isEmpty() && receiptDownloadVo.getPeriods() == null) {
				OrderScheduleDto orderScheduleDto = scheduleMap.get(paymentBizDto.getScheduleId());
				receiptDownloadVo.setPeriods(orderScheduleDto == null ? 0 : orderScheduleDto.getPeriods());
			}
			// 订单信息
			if (orderMap != null && !orderMap.isEmpty()) {
				OrderSubcompanyDto orderSubcompanyDto = orderMap.get(paymentBizDto.getOrderCode());
				if (orderSubcompanyDto != null) {
					receiptDownloadVo.setDeliveryTime(orderSubcompanyDto.getDeliveryTime());
					Integer type = orderSubcompanyDto.getType();
					Integer paymentMethod = orderSubcompanyDto.getPaymentMethod();
					if (type == 2) {
						receiptDownloadVo.setPaymentMethodStr(paymentMethod == 1
								? "专属-全款" : paymentMethod == 2
								? "专属-分期" : null);
					} else if (type == 3) {
						receiptDownloadVo.setPaymentMethodStr("订阅");
					}
					receiptDownloadVo.setSubcompanyName(orderSubcompanyDto.getSubcompanyName());

					// 车辆信息
					CarDto carDto = carMap == null ? null
							: carMap.isEmpty() ? null : carMap.get(orderSubcompanyDto.getCarId());
					receiptDownloadVo.setVin(carDto == null ? null : carDto.getVin());
					receiptDownloadVo.setLicencePlate(carDto == null ? null : carDto.getLicencePlate());
				}
			}

			result.add(receiptDownloadVo);
		}

		return result;
	}

	/**
	 * 查询收款台账导出数据条数
	 * 
	 * @param selectParams
	 * @return
	 * @throws Exception
	 */
	@Override
	public Long getReceiptStandingBookDownloadCount(Map<String, Object> selectParams) throws Exception {
		Long result = 0L;
		// 判断是否选择查询
		String paymentIds = ObjectCastUtil.castString(selectParams.get("paymentIds"));
		if (StringUtils.isNotBlank(paymentIds)) {
			// 选择导出
			selectParams.remove("businessType");
			selectParams.remove("orderCode");
			selectParams.remove("thirdPayNumber");
			selectParams.remove("userName");
			selectParams.remove("startPayTime");
			selectParams.remove("endPayTime");
			selectParams.remove("payWay");
			selectParams.remove("payType");
			selectParams.put("paymentIds", Arrays.asList(paymentIds.split(",")));
		} else {
			// 转换用户信息
			if (!xlateUser(selectParams)) {
				return result;
			}
		}

		return paymentBizService.getReceiptStandingBookDownloadCount(selectParams);
	}

	/**
	 * 异步发送收款台账导出数据
	 * 
	 * @param selectParams
	 * @param user
	 * @return
	 * @throws Exception
	 */
	@Async
	@Override
	public Boolean getReceiptStandingBookDownloadEmail(Map<String, Object> selectParams, UserEntity user)
			throws Exception {
		try {
			String fileName = null;
			Integer businessType = ObjectCastUtil.castInteger(selectParams.get("businessType"));
			if (businessType == null) {
				logger.error("[getReceiptStandingBookDownloadEmail]异步发送收款台账导出数据,业务类型不能为空");
				return false;
			} else if (businessType == 1) {
				fileName = "订阅订单收款台账(" + DateUtil.formatDate(LocalDate.now()) + ")";
			} else if (businessType == 2) {
				fileName = "专属订单收款台账(" + DateUtil.formatDate(LocalDate.now()) + ")";
			} else {
				logger.error("[getReceiptStandingBookDownloadEmail]异步发送收款台账导出数据,业务类型({})错误", businessType);
				return false;
			}

			List<ReceiptDownloadVo> datas = this.getReceiptStandingBookDownload(selectParams);
			// 生成excel
			XSSFWorkbook xssBook = PoiExcelUtil.receiptStandingBook(datas);
			// 发送邮件
			EmailUtil.sendMail(EMAIL_ACCOUNT, EMAIL_PASSWORD, fileName, fileName, user.getAccount(), fileName + ".xlsx",
					xssBook);

			return true;
		} catch (Exception e) {
			logger.error("导出台账发送邮件失败！");
			DingTalkUtil.exceptionSend(EXPLAIN + "导出台账发送邮件失败！");
			return false;
		}
	}

	/**
	 * 转换用户信息
	 * 
	 * @param params
	 */
	private boolean xlateUser(Map<String, Object> params) {
		String userName = ObjectCastUtil.castString(params.get("userName"));
		// 判断查询条件是否有用户信息
		if (StringUtils.isNotBlank(userName)) {
			// 查询用信息
			UserDto UserDto = userService.getUserByName(userName);
			if (UserDto == null) {
				// 用户不存在
				return false;
			}
			Integer userId = UserDto.getId();
			params.put("userId", userId);
			params.remove("userName");
			logger.info("[xlateUser]分页获取收款台账信息userId：" + userId);
		}
		return true;
	}
}
